#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "data_type.h"
#include "bridge_entry.h"
#include "bridge_service.h"

// 结果解析结构体
typedef struct {
    char oid[128];
    char name[128];
    char value[256];
    char type[32];
    int val_int;
    uint64_t val_c64;
    double val_float;
    char val_str[50];
} SNMPResult;

int handler_oid(SNMPResult *res){
    for (size_t i = 0; i < sizeof(oids)/sizeof(oids[0]) && oids[i] != NULL; i++)
    {
        if(0 == strncmp(oids[i], res->oid, strlen(oids[i]))){
            return i;
        }
    }
    return -1;
}

/**
 * 处理远端OSID
 */
BRIDGE_info *handler_remote_oid(SNMPResult *res, BRIDGE_info *info){
    if(0 == strncmp("UBNT-MIB::ubntMIB.4.7.1", res->oid, strlen("UBNT-MIB::ubntMIB.4.7.1"))){
        // 步骤1：提取数字序列
        char sequence[256];
        if (extract_digit_sequence(res->oid, sequence, sizeof(sequence))) {
            printf("提取数字序列失败\n\n");
            return NULL;
        }
        printf("提取序列: %s\n", sequence);
        // 步骤2：转换为十六进制格式
        char hex_output[20];
        if (convert_to_hex_format(sequence, hex_output, sizeof(hex_output))) {
            printf("转换失败\n\n");
            return NULL;
        }
        
        printf("十六进制: %s\n\n", hex_output);
        // 步骤3：转换为十六进制格式
        int remote_cnt = 0;
        if(info->connectNum == 0) {
            info->connect = (BRIDGE_info*)malloc(sizeof(BRIDGE_info));
            memcpy(info->connect[0].mac, hex_output, strlen(hex_output));
            info->connectNum = 1;
            return &(info->connect[0]);
        } else {
            for(int i = 0; i < info->connectNum; i++){
                if(strcmp(info->connect[i].mac, hex_output) == 0){
                    return &(info->connect[i]);
                }
            }
            info->connectNum++;
            info->connect = (BRIDGE_info*)realloc(info->connect, info->connectNum * sizeof(BRIDGE_info));
            memcpy(info->connect[info->connectNum - 1].mac, hex_output, strlen(hex_output));
            return &(info->connect[info->connectNum - 1]);
        }
    }
    return NULL;
}



void parse_oid_result(netsnmp_variable_list *var, SNMPResult *result) {
    // 获取 OID 字符串
    snprint_objid(result->oid, sizeof(result->oid), var->name, var->name_length);
    
    // 获取 OID 名称（MIB 解析）
    struct tree *node = get_tree(var->name, var->name_length, get_tree_head());
    if (node && node->label) {
        snprintf(result->name, sizeof(result->name), "%s", node->label);
    } else {
        snprintf(result->name, sizeof(result->name), "未知OID");
    }
    
    // 解析值类型（兼容所有 SNMP 类型）
    char buf[256];
    switch (var->type) {
        case ASN_INTEGER:
            snprintf(result->type, sizeof(result->type), "整数");
            snprintf(result->value, sizeof(result->value), "%ld", *var->val.integer);
            result->val_int = *var->val.integer;
            break;
            
        case ASN_COUNTER:
            snprintf(result->type, sizeof(result->type), "计数器(32位)");
            snprintf(result->value, sizeof(result->value), "%lu", *var->val.integer);
            result->val_int = *var->val.integer;
            break;
            
        case ASN_COUNTER64:

            struct counter64 *c64 = var->val.counter64;
            uint32_t high = c64->high;
            uint32_t low = c64->low;
            uint64_t full_value = ((uint64_t)high << 32) | low;
            printf("完整64位值: %" PRIu64 "\n", full_value);
            
            snprintf(result->type, sizeof(result->type), "计数器(64位)");
            snprint_value(buf, sizeof(buf), var->name, var->name_length, var);
            snprintf(result->value, sizeof(result->value), "%s", buf);
            result->val_c64 = full_value;
            break;
            
        case ASN_GAUGE:
            snprintf(result->type, sizeof(result->type), "计量器");
            snprintf(result->value, sizeof(result->value), "%lu", *var->val.integer);
            result->val_int = *var->val.integer;
            break;
            
        case ASN_TIMETICKS:
            snprintf(result->type, sizeof(result->type), "时间戳");
            snprintf(result->value, sizeof(result->value), "%.2f秒", (double)(*var->val.integer) / 100.0);
            result->val_int = *var->val.integer;
            break;
            
        case ASN_IPADDRESS:
            snprintf(result->type, sizeof(result->type), "IP地址");
            snprint_value(buf, sizeof(buf), var->name, var->name_length, var);
            snprintf(result->value, sizeof(result->value), "%s", buf);
            uint8_t octets[4];
            if (var->val_len == 4) {
                memcpy(octets, var->val.string, 4);
                snprintf(result->val_str, sizeof(result->val_str), "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]);
            } else {
                fprintf(stderr, "错误：无效的IP地址长度 %zu\n", var->val_len);
            }
            break;
            
        case ASN_OCTET_STR:
            snprintf(result->type, sizeof(result->type), "字符串");
            snprint_value(buf, sizeof(buf), var->name, var->name_length, var);
            snprintf(result->value, sizeof(result->value), "%s", buf);
            break;
            
        case ASN_OBJECT_ID:
            snprintf(result->type, sizeof(result->type), "OID");
            char oid_buf[128];
            snprint_objid(oid_buf, sizeof(oid_buf), var->val.objid, var->val_len / sizeof(oid));
            snprintf(result->value, sizeof(result->value), "%s", oid_buf);
            break;
            
        default:
            snprintf(result->type, sizeof(result->type), "未知类型");
            snprint_value(buf, sizeof(buf), var->name, var->name_length, var);
            snprintf(result->value, sizeof(result->value), "%s", buf);
            break;
    }
}
BRIDGE_info *bridge_snmp_init(char *community, char *version_str, char *target) {
    
    // 协议版本处理（解决 V2 PDU 在 V1 会话的错误）
    int version;
    if (strcmp(version_str, "1") == 0) {
        version = SNMP_VERSION_1;
    } else if (strcmp(version_str, "2c") == 0) {
        version = SNMP_VERSION_2c;
    } else {
        fprintf(stderr, "错误: 不支持的SNMP版本 '%s' (支持 1 或 2c)\n", version_str);
        return NULL;
    }
    
    // 初始化 SNMP 库
    init_snmp("snmp_walker");
    add_mibdir("/usr/share/snmp/mibs");  // OpenWRT 默认 MIB 路径
    read_all_mibs();  // 加载所有可用 MIB
    
    // 创建会话配置
    netsnmp_session session;
    snmp_sess_init(&session);
    session.peername = (char *)target;
    session.version = version;
    session.community = (u_char *)community;
    session.community_len = strlen(community);
    session.timeout = 3000000;   // 3秒超时
    session.retries = 1;          // 失败重试1次
    
    // 打开会话
    netsnmp_session *ss = snmp_open(&session);
    if (!ss) {
        snmp_perror("snmp_open");
        snmp_shutdown("snmp_walker");
        return NULL;
    }
    
    // 创建起始 OID (.iso.org.dod.internet.mgmt.mib-2)
    oid start_oid[MAX_OID_LEN];
    size_t oid_len = MAX_OID_LEN;
    if (!snmp_parse_oid("SNMPv2-SMI::enterprises.41112.1.4", start_oid, &oid_len)) {
        snmp_perror("snmp_parse_oid");
        snmp_close(ss);
        return NULL;
    }
    
    // 动态选择 PDU 类型（避免版本冲突）
    u_char pdu_type;
    if (version == SNMP_VERSION_1) {
        pdu_type = SNMP_MSG_GETNEXT;  // v1 必须用 GETNEXT
    } else {
        pdu_type = SNMP_MSG_GETBULK;  // v2c 用高效 GETBULK
    }
    
    netsnmp_pdu *pdu = snmp_pdu_create(pdu_type);
    if (version == SNMP_VERSION_2c) {
        pdu->non_repeaters = 0;
        pdu->max_repetitions = 50;  // 每次获取50个OID
    }
    snmp_add_null_var(pdu, start_oid, oid_len);
    
    // 结果遍历
    int count = 0;
    netsnmp_variable_list *vars;
    printf("开始 SNMP Walk [%s] 协议: v%s\n", target, version_str);
    printf("==================================================\n");
    BRIDGE_info *info = malloc(sizeof(BRIDGE_info));
    while (1) {
        netsnmp_pdu *response = NULL;
        int status = snmp_synch_response(ss, pdu, &response);
        
        // 错误处理
        if (status != STAT_SUCCESS || !response) {
            snmp_sess_perror("snmpwalk", ss);
            free(info);
            return NULL;
        }
        
        // 协议错误检查
        if (response->errstat != SNMP_ERR_NOERROR) {
            fprintf(stderr, "SNMP 错误: %s\n", snmp_errstring(response->errstat));
            snmp_free_pdu(response);
            return info;
        }
        
        // 遍历并打印结果
        for (vars = response->variables; vars; vars = vars->next_variable) {
            // 检查是否到达MIB末尾
            if (vars->type == SNMP_ENDOFMIBVIEW) {
                printf("已到达MIB末尾\n");
                snmp_free_pdu(response);
                goto cleanup;
            }
            
            SNMPResult result;
            parse_oid_result(vars, &result);
            printf("OID: %s\n", result.oid);
            printf("名称: %s\n", result.name);
            printf("值: %s\n", result.value);
            printf("类型: %s\n", result.type);
            
            char *res = NULL;
            int idx = handler_oid(&result);
            printf("idx:%d\n", idx);

            switch (idx)
            {
            case wirelessMode:
                res = parse_wireless_mode(result.value);
                memset(info->wirelessMode, 0, INFO_LEN);
                memcpy(info->wirelessMode, res, strlen(res));
                break;
            case workingFrequency:
                info->workingFrequency = result.val_int;
                break;
            case transmitPower:
                info->transmitPower = result.val_int;
                break;
            case polarizationSignalDifference:
                info->polarizationSignalDifference = result.val_int;
                break;
            case antennaGain:
                info->antennaGain = extract_number(result.value);
                break;
            case ssid:
                memset(info->ssid, 0, INFO_LEN);
                char *s = extract_quoted_content(result.value);
                if(s){
                    memcpy(info->ssid, s, strlen(s));
                    free(s);
                }
                break;
            case mac:
                memset(info->mac, 0, INFO_LEN);
                char* mac_str = format_mac_address(result.value);
                if(mac_str){
                    memcpy(info->mac, mac_str, strlen(mac_str));
                    free(mac_str);
                }
                break;
            case signalStrength:
                info->signalStrength = result.val_int;
                break;
            case backgroundNoise:
                info->backgroundNoise = result.val_int;
                break;
            case pointDistance:
                info->pointDistance = result.val_int;
                break;
            case encryptionMethod:{
                memset(info->encryptionMethod, 0, INFO_LEN);
                char *ss = extract_quoted_content(result.value);
                if(ss){
                    memcpy(info->encryptionMethod, ss, strlen(ss));
                    free(ss);
                }
                break;
            }
            case channelWidth:
                info->channelWidth = result.val_int;
                break;
            case accessPointsNumber:
                info->accessPointsNumber = result.val_int;
                break;
            /**远端设备信息*/
            case remoteDeviceName:{
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    memset(remote->deviceName, 0, INFO_LEN);
                    memcpy(remote->deviceName, result.val_str, strlen(result.val_str));
                }
                break;
            }
            case remoteSignalStrength:{      
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->signalStrength = result.val_int;
                }
                break;
            }
            case remoteBackgroundNoise:{      
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->backgroundNoise = result.val_int;
                }
                break;
            }
            case remoteCpu:{      
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->cpu = result.val_int;
                }
                break;
            }
            case remoteIp:{      
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    memset(remote->ip, 0, INFO_LEN);
                    memcpy(remote->ip, result.val_str, strlen(result.val_str));
                }
                break;
            }
            case sendBytes:{      
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->sendBytes = result.val_c64;
                }
                break;
            }
            case receivedBytes:{
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->receivedBytes = result.val_c64;
                }
                break;
            }
            case connectTime:{
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->connectTime = result.val_int;
                }
                break;
            }
            case cinrCarrier:{
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->cinrCarrier = result.val_int;
                }
                break;
            }
            case transmissionCapacity:{
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->transmissionCapacity = result.val_int;
                }
                break;
            }
            case receptionThroughput:{
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->receptionThroughput = result.val_int;
                }
                break;
            }
            case delay:{
                BRIDGE_info *remote = handler_remote_oid(&result, info);
                if(remote){
                    remote->delay = result.val_int;
                }
                break;
            }
            case deviceCurrentTime:
                memset(info->deviceCurrentTime, 0, INFO_LEN);
                char *date = extract_time_string(result.value);
                if(date){
                    memcpy(info->deviceCurrentTime, date, strlen(date));
                }
                break;
            case deviceMode:
                res = parse_device_mode(result.value);
                memset(info->deviceMode, 0, INFO_LEN);
                memcpy(info->deviceMode, res, strlen(res));
                break;
            case cpu:
                info->cpu = result.val_int;   
                break;
            }
            printf("--------------------------------------------------\n");
            // 每10个结果暂停一次
            ++count;
            #if 0
            if (++count % 10 == 0) {
                printf("已显示 %d 个结果，按Enter继续...\n", count);
                getchar();
            }
            #endif
        }
        
        // 准备下一个请求

        if (response->variables) {
            pdu = snmp_pdu_create(pdu_type);
            if (version == SNMP_VERSION_2c) {
                pdu->non_repeaters = 0;
                pdu->max_repetitions = 50;
            }
            snmp_add_null_var(pdu, response->variables->name, response->variables->name_length);
        }

        snmp_free_pdu(response);
    }
cleanup:
    printf("==================================================\n");
    printf("操作完成! 共获取 %d 个结果\n", count);
    
    // 清理资源
    snmp_close(ss);
    snmp_shutdown("snmp_walker");
    return info;

}

void free_BridgeInfo(BRIDGE_info *info) {
    if(info != NULL){
        if(info->connect != NULL) {
            free(info->connect);
        }
        free(info);
    } 
}